package org.tigris.subversion.svnant.types;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.selectors.FileSelector;
import org.apache.tools.ant.types.selectors.SelectorUtils;
import org.apache.tools.ant.util.FileUtils;
import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
import org.tigris.subversion.svnclientadapter.ISVNStatus;
import org.tigris.subversion.svnclientadapter.SVNClientException;
import org.tigris.subversion.svnclientadapter.SVNNodeKind;

public class SvnDirScanner extends DirectoryScanner
{
  private static final boolean ON_VMS = Os.isFamily("openvms");

  /** @deprecated */
  protected static final String[] DEFAULTEXCLUDES = { "**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*", "**/CVS", "**/CVS/**", "**/.cvsignore", "**/SCCS", "**/SCCS/**", "**/vssver.scc", "**/.svn", "**/.svn/**", "**/.DS_Store" };
  private static final Vector<String> defaultExcludes = new Vector();
  private static final FileUtils fileUtils = FileUtils.newFileUtils();
  private ISVNClientAdapter svnClient;
  private Map<File, ISVNStatus[]> fileListMap = new HashMap();
  private File basedir;
  private String[] includes;
  private String[] excludes;
  private FileSelector[] selectors = null;
  private Vector<String> filesIncluded;
  private Vector<String> filesNotIncluded;
  private Vector<String> filesExcluded;
  private Vector<String> dirsIncluded;
  private Vector<String> dirsNotIncluded;
  private Vector<String> dirsExcluded;
  private Vector<String> filesDeselected;
  private Vector<String> dirsDeselected;
  private boolean haveSlowResults = false;
  private boolean isCaseSensitive = true;
  private boolean followSymlinks = true;
  private boolean everythingIncluded = true;
  private Set<String> scannedDirs = new HashSet();

  public SvnDirScanner(ISVNClientAdapter paramISVNClientAdapter)
  {
    this.svnClient = paramISVNClientAdapter;
  }

  private ISVNStatus[] list(File paramFile)
  {
	  ISVNStatus[] localObject = (ISVNStatus[])this.fileListMap.get(paramFile);
    if (localObject == null)
    {
      try
      {
        localObject = this.svnClient.getStatus(paramFile, false, true);
      }
      catch (SVNClientException localSVNClientException)
      {
        throw new RuntimeException("Error scanning: " + localSVNClientException, localSVNClientException);
      }
      int i = 0;
      for (int j = 0; j < localObject.length; j++)
      {
        if (false != localObject[j].getFile().equals(paramFile))
          continue;
        i++;
      }
      ISVNStatus[] arrayOfISVNStatus = new ISVNStatus[i];
      int k = 0;
      for (int m = 0; m < localObject.length; m++)
      {
        if (false != localObject[m].getFile().equals(paramFile))
          continue;
        arrayOfISVNStatus[k] = localObject[m];
        k++;
      }
      localObject = arrayOfISVNStatus;
      this.fileListMap.put(paramFile, localObject);
    }
    return  localObject;
  }

  protected static boolean matchPatternStart(String paramString1, String paramString2)
  {
    return SelectorUtils.matchPatternStart(paramString1, paramString2);
  }

  protected static boolean matchPatternStart(String paramString1, String paramString2, boolean paramBoolean)
  {
    return SelectorUtils.matchPatternStart(paramString1, paramString2, paramBoolean);
  }

  protected static boolean matchPath(String paramString1, String paramString2)
  {
    return SelectorUtils.matchPath(paramString1, paramString2);
  }

  protected static boolean matchPath(String paramString1, String paramString2, boolean paramBoolean)
  {
    return SelectorUtils.matchPath(paramString1, paramString2, paramBoolean);
  }

  public static boolean match(String paramString1, String paramString2)
  {
    return SelectorUtils.match(paramString1, paramString2);
  }

  protected static boolean match(String paramString1, String paramString2, boolean paramBoolean)
  {
    return SelectorUtils.match(paramString1, paramString2, paramBoolean);
  }

  public static String[] getDefaultExcludes()
  {
    return (String[])defaultExcludes.toArray(new String[defaultExcludes.size()]);
  }

  public static boolean addDefaultExclude(String paramString)
  {
    if (defaultExcludes.indexOf(paramString) == -1)
    {
      defaultExcludes.add(paramString);
      return true;
    }
    return false;
  }

  public static boolean removeDefaultExclude(String paramString)
  {
    return defaultExcludes.remove(paramString);
  }

  public static void resetDefaultExcludes()
  {
    defaultExcludes.clear();
    for (int i = 0; i < DEFAULTEXCLUDES.length; i++)
      defaultExcludes.add(DEFAULTEXCLUDES[i]);
  }

  public void setBasedir(String paramString)
  {
    setBasedir(new File(paramString.replace('/', File.separatorChar).replace('\\', File.separatorChar)));
  }

  public void setBasedir(File paramFile)
  {
    this.basedir = paramFile;
  }

  public File getBasedir()
  {
    return this.basedir;
  }

  public boolean isCaseSensitive()
  {
    return this.isCaseSensitive;
  }

  public void setCaseSensitive(boolean paramBoolean)
  {
    this.isCaseSensitive = paramBoolean;
  }

  public boolean isFollowSymlinks()
  {
    return this.followSymlinks;
  }

  public void setFollowSymlinks(boolean paramBoolean)
  {
    this.followSymlinks = paramBoolean;
  }

  public void setIncludes(String[] paramArrayOfString)
  {
    if (paramArrayOfString == null)
    {
      this.includes = null;
    }
    else
    {
      this.includes = new String[paramArrayOfString.length];
      for (int i = 0; i < paramArrayOfString.length; i++)
      {
        String str = paramArrayOfString[i].replace('/', File.separatorChar).replace('\\', File.separatorChar);
        if (str.endsWith(File.separator))
          str = str + "**";
        this.includes[i] = str;
      }
    }
  }

  public void setExcludes(String[] paramArrayOfString)
  {
    if (paramArrayOfString == null)
    {
      this.excludes = null;
    }
    else
    {
      this.excludes = new String[paramArrayOfString.length];
      for (int i = 0; i < paramArrayOfString.length; i++)
      {
        String str = paramArrayOfString[i].replace('/', File.separatorChar).replace('\\', File.separatorChar);
        if (str.endsWith(File.separator))
          str = str + "**";
        this.excludes[i] = str;
      }
    }
  }

  public void setSelectors(FileSelector[] paramArrayOfFileSelector)
  {
    this.selectors = paramArrayOfFileSelector;
  }

  public boolean isEverythingIncluded()
  {
    return this.everythingIncluded;
  }

  public void scan()
    throws IllegalStateException
  {
    if (this.basedir == null)
      throw new IllegalStateException("No basedir set");
    if (!this.basedir.exists())
      throw new IllegalStateException("basedir " + this.basedir + " does not exist");
    if (!this.basedir.isDirectory())
      throw new IllegalStateException("basedir " + this.basedir + " is not a directory");
    if (this.includes == null)
    {
      this.includes = new String[1];
      this.includes[0] = "**";
    }
    if (this.excludes == null)
      this.excludes = new String[0];
    this.filesIncluded = new Vector();
    this.filesNotIncluded = new Vector();
    this.filesExcluded = new Vector();
    this.filesDeselected = new Vector();
    this.dirsIncluded = new Vector();
    this.dirsNotIncluded = new Vector();
    this.dirsExcluded = new Vector();
    this.dirsDeselected = new Vector();
    if (isIncluded(""))
    {
      if (!isExcluded(""))
      {
        if (isSelected("", this.basedir))
          this.dirsIncluded.addElement("");
        else
          this.dirsDeselected.addElement("");
      }
      else
        this.dirsExcluded.addElement("");
    }
    else
      this.dirsNotIncluded.addElement("");
    checkIncludePatterns();
    clearCaches();
  }

  private void checkIncludePatterns()
  {
    Hashtable localHashtable = new Hashtable();
    Object localObject1;
    for (int i = 0; i < this.includes.length; i++)
    {
      localObject1 = SelectorUtils.rtrimWildcardTokens(this.includes[i]);
      localHashtable.put(localObject1, this.includes[i]);
    }
    if (localHashtable.containsKey(""))
    {
      scandir(this.basedir, "", true);
    }
    else
    {
      Enumeration localEnumeration = localHashtable.keys();
      localObject1 = null;
      try
      {
        localObject1 = this.basedir.getCanonicalFile();
      }
      catch (IOException localIOException1)
      {
        throw new BuildException(localIOException1);
      }
      while (localEnumeration.hasMoreElements())
      {
        String str1 = (String)localEnumeration.nextElement();
        String str2 = (String)localHashtable.get(str1);
        Object localObject2 = new File(this.basedir, str1);
        if (((File)localObject2).exists())
          try
          {
            File localFile1 = ((File)localObject2).getCanonicalFile();
            String str3 = fileUtils.removeLeadingPath((File)localObject1, localFile1);
            if ((!str3.equals(str1)) || (ON_VMS))
            {
              localObject2 = findFile(this.basedir, str1);
              if (localObject2 != null)
                str1 = fileUtils.removeLeadingPath(this.basedir, (File)localObject2);
            }
          }
          catch (IOException localIOException2)
          {
            throw new BuildException(localIOException2);
          }
        if (((localObject2 == null) || (!((File)localObject2).exists())) && (!this.isCaseSensitive))
        {
          File localFile2 = findFileCaseInsensitive(this.basedir, str1);
          if (localFile2.exists())
          {
            str1 = fileUtils.removeLeadingPath(this.basedir, localFile2);
            localObject2 = localFile2;
          }
        }
        if ((localObject2 != null) && (((File)localObject2).exists()))
        {
          if ((!this.followSymlinks) && (isSymlink(this.basedir, str1)))
            continue;
          if (((File)localObject2).isDirectory())
          {
            if ((isIncluded(str1)) && (str1.length() > 0))
            {
              accountForIncludedDir(str1, (File)localObject2, true);
            }
            else
            {
              if ((str1.length() > 0) && (str1.charAt(str1.length() - 1) != File.separatorChar))
                str1 = str1 + File.separatorChar;
              scandir((File)localObject2, str1, true);
            }
          }
          else if ((this.isCaseSensitive) && (str2.equals(str1)))
            accountForIncludedFile(str1, (File)localObject2);
          else if ((!this.isCaseSensitive) && (str2.equalsIgnoreCase(str1)))
            accountForIncludedFile(str1, (File)localObject2);
        }
      }
    }
  }

  protected void slowScan()
  {
    if (this.haveSlowResults)
      return;
    String[] arrayOfString1 = new String[this.dirsExcluded.size()];
    this.dirsExcluded.copyInto(arrayOfString1);
    String[] arrayOfString2 = new String[this.dirsNotIncluded.size()];
    this.dirsNotIncluded.copyInto(arrayOfString2);
    for (int i = 0; i < arrayOfString1.length; i++)
    {
      if (couldHoldIncluded(arrayOfString1[i]))
        continue;
      scandir(new File(this.basedir, arrayOfString1[i]), arrayOfString1[i] + File.separator, false);
    }
    for (int i = 0; i < arrayOfString2.length; i++)
    {
      if (couldHoldIncluded(arrayOfString2[i]))
        continue;
      scandir(new File(this.basedir, arrayOfString2[i]), arrayOfString2[i] + File.separator, false);
    }
    this.haveSlowResults = true;
  }

  protected void scandir(File paramFile, String paramString, boolean paramBoolean)
  {
    if ((paramBoolean) && (hasBeenScanned(paramString)))
      return;
    ISVNStatus[] arrayOfISVNStatus = list(paramFile);
    if (arrayOfISVNStatus == null)
      throw new BuildException("IO error scanning directory " + paramFile.getAbsolutePath());
    for (int i = 0; i < arrayOfISVNStatus.length; i++)
    {
      String str = paramString + arrayOfISVNStatus[i].getFile().getName();
      File localFile = new File(paramFile, arrayOfISVNStatus[i].getFile().getName());
      if ((SVNNodeKind.DIR == arrayOfISVNStatus[i].getNodeKind()) || ((SVNNodeKind.UNKNOWN == arrayOfISVNStatus[i].getNodeKind()) && (arrayOfISVNStatus[i].getFile().isDirectory())))
      {
        if (isIncluded(str))
        {
          accountForIncludedDir(str, localFile, paramBoolean);
        }
        else
        {
          this.everythingIncluded = false;
          this.dirsNotIncluded.addElement(str);
          if ((paramBoolean) && (couldHoldIncluded(str)))
            scandir(localFile, str + File.separator, paramBoolean);
        }
        if (paramBoolean)
          continue;
        scandir(localFile, str + File.separator, paramBoolean);
      }
      else
      {
        if ((SVNNodeKind.FILE != arrayOfISVNStatus[i].getNodeKind()) && ((SVNNodeKind.UNKNOWN != arrayOfISVNStatus[i].getNodeKind()) || (!arrayOfISVNStatus[i].getFile().isFile())))
          continue;
        if (isIncluded(str))
        {
          accountForIncludedFile(str, localFile);
        }
        else
        {
          this.everythingIncluded = false;
          this.filesNotIncluded.addElement(str);
        }
      }
    }
  }

  private void accountForIncludedFile(String paramString, File paramFile)
  {
    if ((!this.filesIncluded.contains(paramString)) && (!this.filesExcluded.contains(paramString)) && (!this.filesDeselected.contains(paramString)))
      if (!isExcluded(paramString))
      {
        if (isSelected(paramString, paramFile))
        {
          this.filesIncluded.addElement(paramString);
        }
        else
        {
          this.everythingIncluded = false;
          this.filesDeselected.addElement(paramString);
        }
      }
      else
      {
        this.everythingIncluded = false;
        this.filesExcluded.addElement(paramString);
      }
  }

  private void accountForIncludedDir(String paramString, File paramFile, boolean paramBoolean)
  {
    if ((!this.dirsIncluded.contains(paramString)) && (!this.dirsExcluded.contains(paramString)) && (!this.dirsDeselected.contains(paramString)))
      if (!isExcluded(paramString))
      {
        if (isSelected(paramString, paramFile))
        {
          this.dirsIncluded.addElement(paramString);
          if (paramBoolean)
            scandir(paramFile, paramString + File.separator, paramBoolean);
        }
        else
        {
          this.everythingIncluded = false;
          this.dirsDeselected.addElement(paramString);
          if ((paramBoolean) && (couldHoldIncluded(paramString)))
            scandir(paramFile, paramString + File.separator, paramBoolean);
        }
      }
      else
      {
        this.everythingIncluded = false;
        this.dirsExcluded.addElement(paramString);
        if ((paramBoolean) && (couldHoldIncluded(paramString)))
          scandir(paramFile, paramString + File.separator, paramBoolean);
      }
  }

  protected boolean isIncluded(String paramString)
  {
    for (int i = 0; i < this.includes.length; i++)
      if (matchPath(this.includes[i], paramString, this.isCaseSensitive))
        return true;
    return false;
  }

  protected boolean couldHoldIncluded(String paramString)
  {
    for (int i = 0; i < this.includes.length; i++)
      if ((matchPatternStart(this.includes[i], paramString, this.isCaseSensitive)) && (isMorePowerfulThanExcludes(paramString, this.includes[i])))
        return true;
    return false;
  }

  private boolean isMorePowerfulThanExcludes(String paramString1, String paramString2)
  {
    String str = paramString1 + File.separator + "**";
    for (int i = 0; i < this.excludes.length; i++)
      if (this.excludes[i].equals(str))
        return false;
    return true;
  }

  protected boolean isExcluded(String paramString)
  {
    for (int i = 0; i < this.excludes.length; i++)
      if (matchPath(this.excludes[i], paramString, this.isCaseSensitive))
        return true;
    return false;
  }

  protected boolean isSelected(String paramString, File paramFile)
  {
    if (this.selectors != null)
      for (int i = 0; i < this.selectors.length; i++)
        if (!this.selectors[i].isSelected(this.basedir, paramString, paramFile))
          return false;
    return true;
  }

  public String[] getIncludedFiles()
  {
    String[] arrayOfString = new String[this.filesIncluded.size()];
    this.filesIncluded.copyInto(arrayOfString);
    Arrays.sort(arrayOfString);
    return arrayOfString;
  }

  public String[] getNotIncludedFiles()
  {
    slowScan();
    String[] arrayOfString = new String[this.filesNotIncluded.size()];
    this.filesNotIncluded.copyInto(arrayOfString);
    return arrayOfString;
  }

  public String[] getExcludedFiles()
  {
    slowScan();
    String[] arrayOfString = new String[this.filesExcluded.size()];
    this.filesExcluded.copyInto(arrayOfString);
    return arrayOfString;
  }

  public String[] getDeselectedFiles()
  {
    slowScan();
    String[] arrayOfString = new String[this.filesDeselected.size()];
    this.filesDeselected.copyInto(arrayOfString);
    return arrayOfString;
  }

  public String[] getIncludedDirectories()
  {
    String[] arrayOfString = new String[this.dirsIncluded.size()];
    this.dirsIncluded.copyInto(arrayOfString);
    Arrays.sort(arrayOfString);
    return arrayOfString;
  }

  public String[] getNotIncludedDirectories()
  {
    slowScan();
    String[] arrayOfString = new String[this.dirsNotIncluded.size()];
    this.dirsNotIncluded.copyInto(arrayOfString);
    return arrayOfString;
  }

  public String[] getExcludedDirectories()
  {
    slowScan();
    String[] arrayOfString = new String[this.dirsExcluded.size()];
    this.dirsExcluded.copyInto(arrayOfString);
    return arrayOfString;
  }

  public String[] getDeselectedDirectories()
  {
    slowScan();
    String[] arrayOfString = new String[this.dirsDeselected.size()];
    this.dirsDeselected.copyInto(arrayOfString);
    return arrayOfString;
  }

  public void addDefaultExcludes()
  {
    int i = this.excludes == null ? 0 : this.excludes.length;
    String[] arrayOfString1 = new String[i + defaultExcludes.size()];
    if (i > 0)
      System.arraycopy(this.excludes, 0, arrayOfString1, 0, i);
    String[] arrayOfString2 = getDefaultExcludes();
    for (int j = 0; j < arrayOfString2.length; j++)
      arrayOfString1[(j + i)] = arrayOfString2[j].replace('/', File.separatorChar).replace('\\', File.separatorChar);
    this.excludes = arrayOfString1;
  }

  public Resource getResource(String paramString)
  {
    File localFile = fileUtils.resolveFile(this.basedir, paramString);
    return new Resource(paramString, localFile.exists(), localFile.lastModified(), localFile.isDirectory());
  }

  private File findFileCaseInsensitive(File paramFile, String paramString)
  {
    File localFile = findFileCaseInsensitive(paramFile, SelectorUtils.tokenizePath(paramString));
    return localFile == null ? new File(paramFile, paramString) : localFile;
  }

  private File findFileCaseInsensitive(File paramFile, Vector<String> paramVector)
  {
    if (paramVector.isEmpty())
      return paramFile;
    if (!paramFile.isDirectory())
      return null;
    ISVNStatus[] arrayOfISVNStatus = list(paramFile);
    if (arrayOfISVNStatus == null)
      throw new BuildException("IO error scanning directory " + paramFile.getAbsolutePath());
    String str1 = (String)paramVector.remove(0);
    String str2;
    for (int i = 0; i < arrayOfISVNStatus.length; i++)
    {
      str2 = arrayOfISVNStatus[i].getFile().getName();
      if (str2.equals(str1))
        return findFileCaseInsensitive(new File(paramFile, str2), paramVector);
    }
    for (int i = 0; i < arrayOfISVNStatus.length; i++)
    {
      str2 = arrayOfISVNStatus[i].getFile().getName();
      if (str2.equalsIgnoreCase(str1))
        return findFileCaseInsensitive(new File(paramFile, str2), paramVector);
    }
    return null;
  }

  private File findFile(File paramFile, String paramString)
  {
    return findFile(paramFile, SelectorUtils.tokenizePath(paramString));
  }

  private File findFile(File paramFile, Vector<String> paramVector)
  {
    if (paramVector.isEmpty())
      return paramFile;
    if (!paramFile.isDirectory())
      return null;
    ISVNStatus[] arrayOfISVNStatus = list(paramFile);
    if (arrayOfISVNStatus == null)
      throw new BuildException("IO error scanning directory " + paramFile.getAbsolutePath());
    String str1 = (String)paramVector.remove(0);
    for (int i = 0; i < arrayOfISVNStatus.length; i++)
    {
      String str2 = arrayOfISVNStatus[i].getFile().getName();
      if (str2.equals(str1))
        return findFile(new File(paramFile, str2), paramVector);
    }
    return null;
  }

  private boolean isSymlink(File paramFile, String paramString)
  {
    return isSymlink(paramFile, SelectorUtils.tokenizePath(paramString));
  }

  private boolean isSymlink(File paramFile, Vector<String> paramVector)
  {
    if (paramVector.size() > 0)
    {
      String str1 = (String)paramVector.remove(0);
      try
      {
        if (fileUtils.isSymbolicLink(paramFile, str1))
          return true;
        return isSymlink(new File(paramFile, str1), paramVector);
      }
      catch (IOException localIOException)
      {
        String str2 = "IOException caught while checking for links, couldn't get canonical path!";
        System.err.println(str2);
        return false;
      }
    }
    return false;
  }

  private boolean hasBeenScanned(String paramString)
  {
    return !this.scannedDirs.add(paramString);
  }

  private void clearCaches()
  {
    this.fileListMap.clear();
    this.scannedDirs.clear();
  }

  static
  {
    resetDefaultExcludes();
  }
}

/* Location:           C:\Users\Administrator\Desktop\svnant.jar
 * Qualified Name:     org.tigris.subversion.svnant.types.SvnDirScanner
 * JD-Core Version:    0.6.0
 */